/*
 * Copyright (C) 2021 Huawei Device Co., Ltd.
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 * http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package com.to.aboomy.bannersample.util.loading;

import ohos.agp.animation.Animator;
import ohos.agp.animation.AnimatorProperty;
import ohos.agp.animation.AnimatorValue;
import ohos.agp.components.element.Element;
import ohos.agp.render.Arc;
import ohos.agp.render.Canvas;
import ohos.agp.render.Paint;
import ohos.agp.utils.Color;
import ohos.agp.utils.RectFloat;
import ohos.agp.window.service.Display;
import ohos.agp.window.service.DisplayAttributes;
import ohos.agp.window.service.DisplayManager;
import ohos.app.Context;

import java.math.BigDecimal;
import java.util.Optional;

/**
 * 加载Drawable
 *
 * @author czf
 * @since 2021-05-12
 */
public class LoadingBuilder implements AnimatorValue.ValueUpdateListener, Animator.LoopedListener,
        Animator.StateChangedListener {
    /**
     * 外部可以修改，但是不建议
     */
    public static final float DEFAULT_SIZE = 55.0f;
    /**
     * ANIMATION_START_DELAY
     */
    protected static final long ANIMATION_START_DELAY = 333L;
    /**
     * ANIMATION_DURATION
     */
    protected static final long ANIMATION_DURATION = 800L;
    /**
     * ANGLE
     */
    protected static final int ANGLE = 360;
    /**
     * HALF
     */
    protected static final float HALF = 0.5f;
    /**
     * INR
     */
    protected static final float INR = 0.6f;
    /**
     * INITPAINT
     */
    protected static final float INITPAINT = 0.4f;
    /**
     * TWELVE
     */
    protected static final int TWELVE = 12;
    private static final int OUTER_CIRCLE_ANGLE = 320;
    private float mAllSize;
    private float mViewWidth;
    private float mViewHeight;
    private Element.OnChangeListener mCallback;
    private AnimatorValue mFloatValueAnimator;
    private int mCurrAnimatorState = 0;
    private Paint mStrokePaint;
    private RectFloat mOuterCircleRectF;
    private float mDefaultSize = DEFAULT_SIZE;

    // 旋转开始角度
    private int mStartRotateAngle;

    // 旋转角度
    private int mRotateAngle;
    private Arc mArc;

    void init(Context context) {
        mAllSize = dip2px(context, new BigDecimal(Float.toString(mDefaultSize)).
                multiply(new BigDecimal(Float.toString(HALF))).
                subtract(new BigDecimal(Float.toString(TWELVE))).floatValue());
        mViewWidth = dip2px(context, mDefaultSize);
        mViewHeight = dip2px(context, mDefaultSize);
        initAnimators();
    }

    private void initAnimators() {
        mFloatValueAnimator = new AnimatorValue();
        mFloatValueAnimator.setLoopedCount(AnimatorProperty.INFINITE);
        mFloatValueAnimator.setDuration(getAnimationDuration());
        mFloatValueAnimator.setDelay(getAnimationStartDelay());
        mFloatValueAnimator.setCurveType(Animator.CurveType.LINEAR);
    }

    void setCallback(Element.OnChangeListener callback) {
        this.mCallback = callback;
    }

    /**
     * 设置mDefaultSizee大小
     *
     * @param defaultSize 宽
     */
    public void setDefaultSize(int defaultSize) {
        this.mDefaultSize = defaultSize;
    }

    /**
     * 初始化Params
     *
     * @param color color
     * @param colorId colorId
     */
    protected void initParams(Color color, int colorId) {
        mArc = new Arc();

        // 最大尺寸
        float outR = getAllSize();

        // 小圆尺寸
        float inR = outR * INR;

        // 初始化画笔
        if (colorId == 1) {
            initPaint(inR * INITPAINT, new Color(Color.BLACK.getValue()));
        } else {
            initPaint(inR * INITPAINT, color);
        }

        // 旋转角度
        mStartRotateAngle = 0;

        // 圆范围
        mOuterCircleRectF = new RectFloat();
        mOuterCircleRectF.fuse(new BigDecimal(Float.toString(getViewCenterX())).
                        subtract(new BigDecimal(Float.toString(outR))).floatValue(),
                new BigDecimal(Float.toString(getViewCenterY())).
                        subtract(new BigDecimal(Float.toString(outR))).floatValue(),
                new BigDecimal(Float.toString(getViewCenterX())).
                        add(new BigDecimal(Float.toString(outR))).floatValue(),
                new BigDecimal(Float.toString(getViewCenterY())).
                        add(new BigDecimal(Float.toString(outR))).floatValue());
    }

    /**
     * 初始化画笔
     *
     * @param lineWidth 宽度
     * @param color 颜色
     */
    private void initPaint(float lineWidth, Color color) {
        mStrokePaint = new Paint();
        mStrokePaint.setStyle(Paint.Style.STROKE_STYLE);
        mStrokePaint.setStrokeWidth(lineWidth);
        mStrokePaint.setColor(Color.BLACK);
        mStrokePaint.setDither(true);
        mStrokePaint.setFilterBitmap(true);
        mStrokePaint.setStrokeCap(Paint.StrokeCap.ROUND_CAP);
        mStrokePaint.setStrokeJoin(Paint.Join.ROUND_JOIN);
    }

    /**
     * onDraw方法
     *
     * @param canvas 画布
     */
    protected void onDraw(Canvas canvas) {
        canvas.save();
        /*
        外圆
        */
        mArc.setArc(mStartRotateAngle, mRotateAngle, false);
        canvas.drawArc(mOuterCircleRectF, mArc, mStrokePaint);
        canvas.restore();
    }

    /**
     * 设置computeUpdateValue
     *
     * @param animatedValue 动画值
     */
    protected void computeUpdateValue(float animatedValue) {
        mStartRotateAngle = (int) (ANGLE * animatedValue);
        switch (mCurrAnimatorState) {
            case 0:
                mRotateAngle = (int) (OUTER_CIRCLE_ANGLE * animatedValue);
                break;
            case 1:
                mRotateAngle = OUTER_CIRCLE_ANGLE - (int) (OUTER_CIRCLE_ANGLE * animatedValue);
                break;
            default:
                break;
        }
    }

    @Override
    public void onRepeat(Animator animator) {
        // 还原到第一阶段
        mFloatValueAnimator.setCurveType(Animator.CurveType.ACCELERATE_DECELERATE);
        mCurrAnimatorState = mCurrAnimatorState == 0 ? 1 : 0;
    }

    /**
     * 设置computeUpdateValue
     */
    public void setRepeat() {
        // 还原到第一阶段
        mFloatValueAnimator.setCurveType(Animator.CurveType.ACCELERATE_DECELERATE);
        mCurrAnimatorState = mCurrAnimatorState == 0 ? 1 : 0;
    }

    void draw(Canvas canvas) {
        onDraw(canvas);
    }

    void start() {
        if (mFloatValueAnimator.isRunning()) {
            return;
        }
        mFloatValueAnimator.setValueUpdateListener(this);
        mFloatValueAnimator.setStateChangedListener(this);
        mFloatValueAnimator.setLoopedListener(this);
        mFloatValueAnimator.setLoopedCount(AnimatorProperty.INFINITE);
        mFloatValueAnimator.setDuration(getAnimationDuration());
        mFloatValueAnimator.start();
    }

    void stop() {
        mFloatValueAnimator.setValueUpdateListener(null);
        mFloatValueAnimator.setLoopedListener(null);
        mFloatValueAnimator.setLoopedCount(0);
        mFloatValueAnimator.setDuration(0);
        mFloatValueAnimator.end();
    }

    @Override
    public void onUpdate(AnimatorValue animation, float v) {
        computeUpdateValue(v);
        invalidateSelf();
    }

    private void invalidateSelf() {
        if (mCallback != null) {
            mCallback.onChange(null);
        }
    }

    @Override
    public void onStart(Animator animator) {
    }

    @Override
    public void onEnd(Animator animator) {
    }

    @Override
    public void onCancel(Animator animator) {
    }

    @Override
    public void onResume(Animator animator) {
    }

    @Override
    public void onStop(Animator animator) {
    }

    @Override
    public void onPause(Animator animator) {
    }

    /**
     * getAnimationStartDelay
     *
     * @return long
     */
    protected long getAnimationStartDelay() {
        return ANIMATION_START_DELAY;
    }

    /**
     * 获取动画持续时间
     *
     * @return float
     */
    protected long getAnimationDuration() {
        double mDurationTimePercent = 1.0;
        return ceil(ANIMATION_DURATION * mDurationTimePercent);
    }

    /**
     * getIntrinsicHeight
     *
     * @return float
     */
    protected float getIntrinsicHeight() {
        return mViewHeight;
    }

    /**
     * getIntrinsicWidth
     *
     * @return float
     */
    protected float getIntrinsicWidth() {
        return mViewWidth;
    }

    /**
     * getViewCenterX
     *
     * @return float
     */
    protected final float getViewCenterX() {
        return getIntrinsicWidth() * HALF;
    }

    /**
     * getViewCenterY
     *
     * @return float
     */
    protected final float getViewCenterY() {
        return getIntrinsicHeight() * HALF;
    }

    /**
     * getAllSize
     *
     * @return float
     */
    protected final float getAllSize() {
        return mAllSize;
    }

    /**
     * dp转px
     *
     * @param context 上下文
     * @param dpValue dpValue
     * @return float
     */
    public static float dip2px(Context context, float dpValue) {
        DisplayAttributes displayAttributes = getScreenPiex(context);
        return dpValue * displayAttributes.scalDensity;
    }

    /**
     * 获取屏幕图片
     *
     * @param context 上下文
     * @return displayAttributes
     */
    public static DisplayAttributes getScreenPiex(Context context) {
        Optional<Display> display = DisplayManager.getInstance().getDefaultDisplay(context);
        return display.get().getAttributes();
    }

    /**
     * 路径
     *
     * @param value value
     * @return Math.ceil(value)
     */
    protected static long ceil(double value) {
        return (long) Math.ceil(value);
    }
}

